package cn.matezk.lianlian.framework;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.util.concurrent.TimeUnit;

@Component
public class RedisMutexLock {
    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    public boolean tryLock(String key, int expireTime) throws InterruptedException {
        long endTime = System.currentTimeMillis() + expireTime * 1000 + 1;
        while (System.currentTimeMillis() <= endTime) {
            if (lock(key, expireTime * 1000))
                return true;
            Thread.sleep(20);
        }
        return false;
    }

    public boolean lock(String key, int expireTime) {
        long expires = System.currentTimeMillis() + expireTime + 1;
        String expiresStr = String.valueOf(expires);
        if (redisTemplate.opsForValue().setIfAbsent(key, expiresStr)) {
            redisTemplate.expire(key, expireTime, TimeUnit.MILLISECONDS);
            // 如果key不存在，设置成功，获取锁
            return true;
        }
        // 如果key已存在，获取存储的时间
        String currentValueStr = redisTemplate.opsForValue().get(key);
        if (currentValueStr != null && Long.parseLong(currentValueStr) < System.currentTimeMillis()) {
            // 锁已过期，设置新的过期时间
            String oldValueStr = redisTemplate.opsForValue().getAndSet(key, expiresStr);
            if (oldValueStr != null && oldValueStr.equals(currentValueStr)) {
                // 比较并交换成功，获取锁
                return true;
            }
        }
        // 其他情况，无法获取锁
        return false;
    }

    public void unlock(String key) {
        String currentValueStr = redisTemplate.opsForValue().get(key);
        if (currentValueStr != null) {
            Long expires = Long.parseLong(currentValueStr);
            if (expires > System.currentTimeMillis()) {
                // 只有锁未过期，才进行删除操作
                redisTemplate.opsForValue().getOperations().delete(key);
            }
        }
    }
}
